package com.brainhealth.customer.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.brainhealth.common.constant.CacheConstants;
import com.brainhealth.common.constant.NumberConstants;
import com.brainhealth.common.core.redis.RedisCache;
import com.brainhealth.common.enums.*;
import com.brainhealth.common.utils.*;
import com.brainhealth.customer.domain.*;
import com.brainhealth.customer.domain.params.ScoreRechargeParam;
import com.brainhealth.customer.domain.vo.*;
import com.brainhealth.customer.mapper.CustomerExerciseMapper;
import com.brainhealth.customer.mapper.ExerciseOrderPayMapper;
import com.brainhealth.customer.mapper.ScoreMallOrderMapper;
import com.brainhealth.customer.service.*;
import com.brainhealth.utils.AdapayUtils;
import com.brainhealth.utils.CommonUtils;
import com.huifu.adapay.core.AdapayCore;
import com.huifu.adapay.core.util.AdapaySign;
import io.jsonwebtoken.lang.Assert;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * 积分服务
 *
 * @author wll
 */
@Service
public class IScoreServiceImpl implements IScoreService {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String INSERT_RESULT = "INSERT_RESULT";
    public static final String UPDATE_RESULT = "UPDATE_RESULT";

    @Autowired
    RedisCache redisCache;

    @Resource
    RedissonClient redissonClient;

    @Autowired
    ICustomerService customerService;

    @Autowired
    IChatService chatService;

    @Autowired
    IScoreRecordService scoreRecordService;

    @Autowired
    IScoreConsumeRecordService scoreConsumeRecordService;

    @Autowired
    ICustomerExerciseService customerExerciseService;

    @Autowired
    IScoreMallOrderService scoreMallOrderService;

    @Autowired
    ExerciseOrderPayMapper exerciseOrderPayMapper;

    @Autowired
    CustomerExerciseMapper customerExerciseMapper;

    @Autowired
    ScoreMallOrderMapper scoreMallOrderMapper;

    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public ScoreMallOrder createScoreRechargeOrder(HttpServletRequest request, ScoreRechargeParam scoreRechargeParam) {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}, 创建积分充值订单, 入参{}", ts, scoreRechargeParam);
            Customer customer = CommonUtils.getCustomerByRequest(request);
            Long customerId = customer.getCustomerId();
            String strCustomerId = null == customerId ? "" : String.valueOf(customerId);
            Date now = DateUtils.getNowDate();
            Long payAmount = scoreRechargeParam.getPayAmount();
            payAmount = null == payAmount ? NumberConstants.ZERO : payAmount;
            PayType payType = scoreRechargeParam.getPayType();
            payType = null == payType ? PayType.Wechat : payType;

            ScoreMallOrder scoreMallOrder = new ScoreMallOrder();
            scoreMallOrder.setScoreMallOrderId(SnowFlakeUtil.getDefaultSnowFlakeId().toString());
            scoreMallOrder.setCustomerId(customerId);
            scoreMallOrder.setTotalPayAmount(payAmount);
            scoreMallOrder.setPayType(payType);
            scoreMallOrder.setStatus(PayStatus.Unpaid.getCode());
            scoreMallOrder.setYn(YNEnum.NO.getCode());
            scoreMallOrder.setCreateBy(strCustomerId);
            scoreMallOrder.setCreateTime(now);
            scoreMallOrder.setUpdateBy(strCustomerId);
            scoreMallOrder.setUpdateTime(now);
            int result = scoreMallOrderService.insertScoreMallOrder(scoreMallOrder);
            if (result > 0) {
                try {
                    redisCache.setCacheObject(CacheConstants.SCORE_ORDER_TIME + customer.getPhone(), DateCalcUtils.addMinute(scoreMallOrder.getCreateTime(), NumberConstants.THIRTY), NumberConstants.THIRTY, TimeUnit.MINUTES);
                    RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque("async-hand-score-recharge-msg");
                    RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
                    delayedQueue.offer(scoreMallOrder.getScoreMallOrderId(), Long.valueOf(NumberConstants.THIRTY), TimeUnit.MINUTES);
                    String s = TimeUnit.SECONDS.toSeconds(NumberConstants.THIRTY) + "分钟";
                    logger.info("添加延时队列成功 ，延迟时间：" + s);
                    return scoreMallOrder;
                } catch (Exception e) {
                    logger.error("ts:{}, 添加延时队列失败", ts, e);
                }
            }
            return scoreMallOrder;
        } catch (Exception e) {
            //todo 支付出现异常把订单处理为异常订单
            logger.info("ts{}创建积分充值订单异常", ts, e);
            return null;
        }
    }

    @Override
    public ScoreMallOrder scoreRechargeOrderPay(HttpServletRequest request, ScoreRechargeParam rechargeParam) {
        Long ts = DateUtils.getTimeMillis();
        checkRechargeParam(rechargeParam);
        logger.info("ts{},积分充值,入参{}", ts, rechargeParam);
        ScoreMallOrder scoreMallOrder = scoreMallOrderService.selectScoreMallOrderByOrderId(rechargeParam.getOrderId());
        if (scoreMallOrder.getStatus() != PayStatus.Unpaid) {
            return null;
        }
        if (scoreMallOrder.getStatus() == PayStatus.Unpaid && !StringUtils.isNullOrEmpty(scoreMallOrder.getPayUrl())) {
            return scoreMallOrder;
        }
        try {
            scoreMallOrder.setTotalPayAmount(rechargeParam.getPayAmount());
            scoreMallOrder.setPayType(rechargeParam.getPayType());
            int updateResult = scoreMallOrderService.updateScoreMallOrder(scoreMallOrder);
            logger.info("ts:{}, 更新订单{}结果{}", ts, rechargeParam.getOrderId(), updateResult);

            AdapayUtils.initAdapay();
            //todo 测试支付订单金额写死 0.01   必须是带小数的数据
            //exerciseOrder.setPayAmount(new BigDecimal(0.01));
            BigDecimal payAmount = new BigDecimal("0.01");
            Map<String, Object> paymentResult = AdapayUtils.executePayment(rechargeParam.getOrderId(), rechargeParam.getPayType(), payAmount, rechargeParam.getOpenId(), PayBusinessType.SCORE_RECHARGE);
            ExerciseOrderPay scoreMallOrderPay = new ExerciseOrderPay();
            scoreMallOrderPay.setOrderId(rechargeParam.getOrderId());
            scoreMallOrderPay.setAdapayRequest(JSON.toJSONString(rechargeParam));
            scoreMallOrderPay.setAdapayResponse(JSON.toJSONString(paymentResult));
            scoreMallOrderPay.setCreateTime(new Date());
            exerciseOrderPayMapper.insertExerciseOrderPay(scoreMallOrderPay);
            if (paymentResult.get("status").equals("succeeded")) {
                JSONObject obj = JSONObject.parseObject(paymentResult.get("expend").toString());
                String resUrl = obj.get("pay_info").toString();
                scoreMallOrder.setPayType(rechargeParam.getPayType());
                //DecimalFormat df1 = new DecimalFormat("0.00");
                //scoreMallOrder.setTotalPayAmount(new BigDecimal(df1.format(scoreMallOrder.getTotalPayAmount())));
                scoreMallOrder.setTotalPayAmount(scoreMallOrder.getTotalPayAmount());
                scoreMallOrder.setPayUrl(resUrl);
                scoreMallOrder.setUpdateTime(new Date());
                scoreMallOrderService.updateScoreMallOrder(scoreMallOrder);

                return scoreMallOrder;
            }
            return null;
        } catch (Exception e) {
            //todo 支付出现异常把订单处理为异常订单
            logger.error("支付接口调用失败！{}", e.getMessage());
            return null;
        }
    }


    void checkRechargeParam(ScoreRechargeParam rechargeParam)
    {
        Assert.state(checkPayAmount(rechargeParam.getPayAmount()),"积分充值金额只能是1到99的整数");
    }

    boolean checkPayAmount(Long payAmount)
    {
        if (null==payAmount)
        {
            return false;
        }
        int intValue = payAmount.intValue();
        return NumberUtils.isNumInRange(NumberConstants.ONE,NumberConstants.ONE_HUNDRED,intValue);
    }

    @Transactional(rollbackFor = Exception.class)
    public Map updateScore(Long ts, Customer customer, ScoreTypeEnum scoreTypeEnum, Long payAmount) {
        ScoreRecord scoreRecord = constructScoreRecord(customer, scoreTypeEnum, payAmount);
        int insertResult = scoreRecordService.insertScoreRecord(scoreRecord);
        logger.info("ts{}用户{}领取新用户见面礼结果{}", ts, scoreRecord.getCustomerId(), insertResult);
        Long score = customer.getScore();
        score = null == score ? Long.valueOf(NumberConstants.ZERO) : score;
        score = score + scoreRecord.getScore();
        customer.setScore(score);
        int updateResult = customerService.updateCustomer(customer);
        logger.info("ts{}用户{}更新积分结果{}", ts, scoreRecord.getCustomerId(), updateResult);
        /**
         * 刷新缓存积分
         */
        customerService.refreshToken(ts,customer);
        Map<String, Integer> map = new HashMap();
        map.put(INSERT_RESULT, insertResult);
        map.put(UPDATE_RESULT, updateResult);
        return map;
    }

    private ScoreRecord constructScoreRecord(Customer customer, ScoreTypeEnum scoreTypeEnum, Long amount) {
        Long customerId = customer.getCustomerId();
        String strCustomerId = null == customerId ? "" : String.valueOf(customerId);
        Date now = DateUtils.getNowDate();

        Integer maxRecordId = scoreRecordService.getMaxRecordId();
        maxRecordId = null == maxRecordId ? NumberConstants.ONE : maxRecordId + 1;
        ScoreRecord scoreRecord = new ScoreRecord();
        scoreRecord.setRecordId(Long.valueOf(maxRecordId));
        scoreRecord.setCustomerId(customerId);
        scoreRecord.setScoreType(scoreTypeEnum.getCode());
        if (scoreTypeEnum.equals(ScoreTypeEnum.RECHARGE)) {
            scoreRecord.setScore(amount * NumberConstants.ONE_HUNDRED);
        } else {
            scoreRecord.setScore(Long.valueOf(scoreTypeEnum.getScore()));
        }
        scoreRecord.setScoreDesc(scoreTypeEnum.getInfo());
        scoreRecord.setYn(YNEnum.NO.getCode());
        scoreRecord.setCreateUser(strCustomerId);
        scoreRecord.setCreateTime(now);
        scoreRecord.setUpdateUser(strCustomerId);
        scoreRecord.setUpdateTime(now);

        return scoreRecord;
    }


    @Override
    public Date getScoreRechargeOrderRemainTime(HttpServletRequest request) {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        Date orderTime = redisCache.getCacheObject(CacheConstants.SCORE_ORDER_TIME + customer.getPhone());
        if (orderTime == null) {
            return null;
        }
        return orderTime;
    }

    @Override
    public void scoreRechargeOrderCallback(HttpServletRequest request, HttpServletResponse response) {
        try
        {
            //验签请参data
            String data = request.getParameter("data");
            //验签请参sign
            String sign = request.getParameter("sign");
            //验签标记
            boolean checkSign;
            //验签请参publicKey
            String publicKey = AdapayCore.PUBLIC_KEY;
            logger.info("验签请参：data={}sign={}");
            //验签
            checkSign = AdapaySign.verifySign(data, sign, publicKey);
            //验签成功逻辑
            JSONObject adapayObject = JSONObject.parseObject(data);
            if (checkSign) {
                //验签成功逻辑
                String orderId = adapayObject.get("order_no").toString();
                if (adapayObject.get("status").equals("succeeded")) {
                    String adapayId = adapayObject.get("id").toString();
                    scoreRechargeOrderSuccess(orderId, adapayId);
                } else {
                    //订单回调支付失败，修改订单状态为失败
                    ScoreMallOrder order = scoreMallOrderService.selectScoreMallOrderByOrderId(orderId);
                    order.setStatus(PayStatus.Failed);
                    order.setUpdateTime(new Date());
                    scoreMallOrderService.updateScoreMallOrder(order);
                }
                logger.info("成功返回数据data:" + data);
            } else {
                //验签失败逻辑
                logger.error("异步回调验签失败！" + data);
            }
            ExerciseOrderPay orderPay = new ExerciseOrderPay();
            orderPay.setCreateTime(new Date());
            orderPay.setAdapayRequest("汇付返回支付回调");
            orderPay.setOrderId(adapayObject.get("order_no").toString());
            orderPay.setAdapayResponse(data);
            response.setStatus(200);
            exerciseOrderPayMapper.insertExerciseOrderPay(orderPay);
        } catch (Exception e) {
            logger.error("异步回调异常", e);
        }
    }

    public boolean scoreRechargeOrderSuccess(String orderId, String adapayId) {
        long ts = DateUtils.getTimeMillis();
        if (lock.tryLock()) {
            try {
                ScoreMallOrder scoreMallOrder = scoreMallOrderService.selectScoreMallOrderByOrderId(orderId);
                logger.info("支付前开始获取订单信息" + JSON.toJSON(scoreMallOrder));
                if (scoreMallOrder.getStatus() == PayStatus.Unpaid) {
                    scoreMallOrder.setStatus(PayStatus.Paid);
                    scoreMallOrder.setTransactionNo(adapayId);
                    scoreMallOrder.setPayTime(new Date());
                    scoreMallOrderService.updateScoreMallOrder(scoreMallOrder);
                    logger.info("ts:{}, 修改订单支付状态结果:{}", ts, JSON.toJSON(scoreMallOrder));

                    Long customerId = scoreMallOrder.getCustomerId();
                    Customer customer = customerService.selectCustomerByCustomerId(customerId);
                    //更新积分
                    Map<String, Integer> map = updateScore(ts, customer, ScoreTypeEnum.RECHARGE, scoreMallOrder.getTotalPayAmount());
                    Integer insertResult = map.get(INSERT_RESULT);
                    Integer updateResult = map.get(UPDATE_RESULT);
                    if (insertResult > 0 && updateResult > 0) {
                        return true;
                    }
                }
            } catch (Exception e) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                logger.error("ts:{}, 订单支付回调异常！", ts, e);
                return false;
            } finally {
                lock.unlock();
            }
        }
        return false;
    }

    @Override
    public ScoreMallOrder getScoreMallOrder(String orderId) {
        return scoreMallOrderService.selectScoreMallOrderByOrderId(orderId);
    }


    @Override
    public List<ScoreMallOrder> getSoreOrderList(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            ScoreMallOrder mallOrder = new ScoreMallOrder();
            mallOrder.setCustomerId(customerId);
            mallOrder.setYn(YNEnum.NO.getCode());
            List<Integer> payTypeList = new ArrayList<Integer>() {{
                add(PayType.Alipay.getCode());
                add(PayType.Wechat.getCode());
            }};
            mallOrder.setPayTypeList(payTypeList);

            List<ScoreMallOrder> scoreMallOrderList = scoreMallOrderService.getScoreMallOrderList(mallOrder);

            return scoreMallOrderList;
        } catch (Exception e) {
            logger.error("ts{}查询积分充值订单列表异常", ts, e);
            return null;
        }
    }

    @Override
    public List<ScoreRechargeOrderVO> getScoreRechargeOrderVOList(List<ScoreMallOrder> scoreMallOrderList) {
        if (CollectionUtils.isEmpty(scoreMallOrderList)) {
            return null;
        }
        List<ScoreRechargeOrderVO> rechargeOrderVOList = new ArrayList<>();
        ScoreRechargeOrderVO rechargeOrderVO = null;
        for (ScoreMallOrder scoreMallOrder : scoreMallOrderList) {
            rechargeOrderVO = new ScoreRechargeOrderVO();
            BeanUtils.copyProperties(scoreMallOrder, rechargeOrderVO);
            Long totalPayAmount = scoreMallOrder.getTotalPayAmount();
            long rechargeScoreAmount = null == totalPayAmount ? 0 : totalPayAmount * NumberConstants.ONE_HUNDRED;
            rechargeOrderVO.setRechargeScoreAmount(rechargeScoreAmount);
            String strCreateTime = null == rechargeOrderVO.getCreateTime() ? "" : DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, rechargeOrderVO.getCreateTime());
            rechargeOrderVO.setStrCreateTime(strCreateTime);
            String strPayType = null == rechargeOrderVO.getPayType() ? "" : rechargeOrderVO.getPayType().getInfo();
            rechargeOrderVO.setStrPayType(strPayType);
            String strStatus = null == rechargeOrderVO.getStatus() ? "" : rechargeOrderVO.getStatus().getInfo();
            rechargeOrderVO.setStrStatus(strStatus);
            rechargeOrderVOList.add(rechargeOrderVO);
        }
        return rechargeOrderVOList;
    }

    @Override
    public ScoreBase getScoreBase(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            //积分基础信息
            ScoreBase scoreBase = getScoreBase(ts, customerId);
            return scoreBase;
        } catch (Exception e) {
            logger.error("ts{}查询积分基础信息异常", ts, e);
            return null;
        }
    }

    @Override
    public ScoreVO getScore(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            ScoreVO scoreVO = new ScoreVO();
            //积分基础信息
            ScoreBase scoreBase = getScoreBase(ts, customerId);
            //积分明细
            ScoreDetail scoreDetail = getScoreDetail(ts, customerId);
            //今日任务奖励
            ChatBase chatBase = chatService.getChatBase(request);
            ScoreTodayTaskReward todayTaskReward = getTodayTaskReward(ts, chatBase.getCustomerId(), chatBase.getOrderNo(), chatBase.getCourseNo());
            //铁人挑战
            ScoreIronManChallenge ironManChallenge = getIronManChallenge(ts, chatBase.getCustomerId(), chatBase.getOrderNo(), chatBase.getCourseNo());
            scoreVO.setScoreBase(scoreBase);
            scoreVO.setScoreDetail(scoreDetail);
            scoreVO.setTodayTaskReward(todayTaskReward);
            scoreVO.setIronManChallenge(ironManChallenge);
            return scoreVO;
        } catch (Exception e) {
            logger.error("ts{}查询我的积分异常", ts, e);
            return null;
        }
    }

    private ScoreBase getScoreBase(Long ts, Long customerId) {
        Customer customerParam = new Customer();
        customerParam.setCustomerId(customerId);
        Customer customer = customerService.selectCustomerByCustomerId(customerId);
        if (null == customer) {
            logger.info("ts{}用户{}为空", ts, customerId);
            return null;
        }
        ScoreBase scoreBase = new ScoreBase();
        BeanUtils.copyProperties(customer, scoreBase);
        return scoreBase;
    }


    private ScoreDetail getScoreDetail(Long ts, Long customerId) {
        ScoreRecord scoreRecordParam = new ScoreRecord();
        scoreRecordParam.setCustomerId(customerId);
        ScoreDetail scoreDetail = scoreRecordService.getScoreDetail(scoreRecordParam);
        if (null == scoreDetail) {
            scoreDetail = new ScoreDetail();
            scoreDetail.setDailyTrainReward(Long.valueOf(NumberConstants.ZERO));
            scoreDetail.setFriendHelpReward(Long.valueOf(NumberConstants.ZERO));
            scoreDetail.setIronChallengeReward(Long.valueOf(NumberConstants.ZERO));
        }
        logger.info("ts{}用户{}积分明细{}", ts, customerId, scoreDetail);
        return scoreDetail;
    }

    private ScoreTodayTaskReward getTodayTaskReward(Long ts, Long customerId, String orderId, Long countSort) {
        Integer completedAllTrainFlag = YNEnum.NO.getCode();
        Integer completedVideoTrainFlag = YNEnum.NO.getCode();
        Integer completedBrainTrainFlag = YNEnum.NO.getCode();
        String videoTrainName = "";
        String brainTrainName = "";
        CustomerExercise customerExerciseParam = new CustomerExercise();
        customerExerciseParam.setCustomerId(customerId);
        customerExerciseParam.setCountSort(countSort);
        List<CustomerExercise> customerExerciseList = customerExerciseService.selectCustomerExerciseList(customerExerciseParam);
        if (CollectionUtils.isEmpty(customerExerciseList)) {
            logger.info("ts{}用户{}订单{}课程{}为空", ts, customerId, orderId, countSort);
            return null;
        }
        CustomerExercise customerExercise = customerExerciseList.stream().filter(item -> Long.valueOf(ExerciseType.Video.getCode()).equals(item.getExerciseType())).findFirst().orElseGet(null);
        if (null != customerExercise && null != customerExercise.getExerciseName()) {
            videoTrainName = customerExercise.getExerciseName();
        }
        if (null != customerExercise && CustomerExerciseStatus.Finished.equals(customerExercise.getStatus())) {
            completedVideoTrainFlag = YNEnum.YES.getCode();
        }
        customerExercise = customerExerciseList.stream().filter(item -> Long.valueOf(ExerciseType.Game.getCode()).equals(item.getExerciseType())).findFirst().orElseGet(null);
        if (null != customerExercise && CustomerExerciseStatus.Finished.equals(customerExercise.getStatus())) {
            completedBrainTrainFlag = YNEnum.YES.getCode();
        }
        if (null != customerExercise && null != customerExercise.getExerciseName()) {
            brainTrainName = customerExercise.getExerciseName();
        }
        Integer completedTaskFlag = YNEnum.NO.getCode();
        if (completedVideoTrainFlag == YNEnum.YES.getCode() && completedBrainTrainFlag == YNEnum.YES.getCode()) {
            completedAllTrainFlag = YNEnum.YES.getCode();
            completedTaskFlag = YNEnum.YES.getCode();
        }
        ScoreTodayTaskReward scoreTodayTaskReward = new ScoreTodayTaskReward();
        scoreTodayTaskReward.setCompletedVideoTrainFlag(completedVideoTrainFlag);
        scoreTodayTaskReward.setCompletedBrainTrainFlag(completedBrainTrainFlag);
        scoreTodayTaskReward.setCompletedAllTrainFlag(completedAllTrainFlag);
        scoreTodayTaskReward.setCompletedTaskFlag(completedTaskFlag);
        scoreTodayTaskReward.setVideoTrainName(videoTrainName);
        scoreTodayTaskReward.setBrainTrainName(brainTrainName);
        return scoreTodayTaskReward;
    }

    private ScoreIronManChallenge getIronManChallenge(Long ts, Long customerId, String orderId, Long countSort) {
        ScoreIronManChallenge challenge = new ScoreIronManChallenge();

        CustomerExercise exercise = new CustomerExercise();
        exercise.setCustomerId(customerId);
        exercise.setOrderId(orderId);
        List<CustomerExercise> customerExerciseList = customerExerciseMapper.selectCustomerExerciseList(exercise);

        Integer persistenceDays = 0;
        for (Long i = countSort; i >= 1; i--) {
            final Long countSortTmp = i;
            boolean breakFlag = false;
            List<CustomerExercise> exerciseList = customerExerciseList.stream().filter(item -> item.getCountSort().equals(countSortTmp)).collect(Collectors.toList());
            for (CustomerExercise exerciseItem : exerciseList) {
                if (exerciseItem.getStatus() != CustomerExerciseStatus.Finished) {
                    breakFlag = true;
                    break;
                }
            }
            if (!breakFlag) {
                persistenceDays++;
            } else {
                //第1节课完成，第2节课未开始
                if (persistenceDays == 0) {
                    continue;
                } else {
                    break;
                }
            }
        }

        if (persistenceDays == 0) {
            persistenceDays = 0;
        } else {
            persistenceDays = persistenceDays % NumberConstants.THREE;
            List<CustomerExercise> exerciseList = customerExerciseList.stream().filter(item -> item.getCountSort().equals(countSort)).collect(Collectors.toList());

            if (persistenceDays == 0) {
                boolean matchResult = exerciseList.stream().allMatch(item -> CustomerExerciseStatus.Finished.equals(item.getStatus()));
                if (matchResult) {
                    persistenceDays = NumberConstants.THREE;
                } else {
                    persistenceDays = 0;
                }
            }

        }

        challenge.setPersistenceDays(persistenceDays);
        return challenge;
    }


    @Override
    public List<ScoreRecord> getScoreRecordList(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            ScoreRecord record = new ScoreRecord();
            record.setCustomerId(customerId);
            List<ScoreRecord> scoreRecordList = scoreRecordService.selectScoreRecordList(record);
            if (CollectionUtils.isEmpty(scoreRecordList)) {
                logger.info("ts{}用户{}无积分获取记录", ts, customerId);
                return new ArrayList<>();
            }
            return scoreRecordList;
        } catch (Exception e) {
            logger.error("ts{}查询积分获取记录异常", ts, e);
            return null;
        }
    }

    @Override
    public List<ScoreRecordVO> getScoreRecordVOList(List<ScoreRecord> scoreRecordList) {
        long ts = DateUtils.getTimeMillis();
        try {

            if (CollectionUtils.isEmpty(scoreRecordList)) {
                logger.info("ts{}用户{}无积分获取记录", ts);
                return new ArrayList<>();
            }
            logger.info("ts{}用户{}积分获取记录条数{}", ts, scoreRecordList.size());
            List<ScoreRecordVO> scoreRecordVOList = scoreRecord2ScoreRecordVOList(scoreRecordList);
            return scoreRecordVOList;
        } catch (Exception e) {
            logger.error("ts{}查询积分获取记录异常", ts, e);
            return null;
        }
    }


    @Override
    public List<ScoreRecordVO> getScoreRecord(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            ScoreRecord record = new ScoreRecord();
            record.setCustomerId(customerId);
            List<ScoreRecord> scoreRecordList = scoreRecordService.selectScoreRecordList(record);
            if (CollectionUtils.isEmpty(scoreRecordList)) {
                logger.info("ts{}用户{}无积分获取记录", ts, customerId);
                return new ArrayList<>();
            }
            logger.info("ts{}用户{}积分获取记录条数{}", ts, customerId, scoreRecordList.size());
            List<ScoreRecordVO> scoreRecordVOList = scoreRecord2ScoreRecordVOList(scoreRecordList);
            return scoreRecordVOList;
        } catch (Exception e) {
            logger.error("ts{}查询积分获取记录异常", ts, e);
            return null;
        }
    }

    /**
     * 转为页面展示字段
     *
     * @param scoreRecordList
     * @return
     */
    private <T> List<ScoreRecordVO> scoreRecord2ScoreRecordVOList(List<T> scoreRecordList) throws NoSuchFieldException {
        if (CollectionUtils.isEmpty(scoreRecordList)) {
            return null;
        }
        List<ScoreRecordVO> scoreRecordVOList = new ArrayList<>();
        ScoreRecordVO scoreRecordVO = null;
        for (T scoreRecord : scoreRecordList) {
            scoreRecordVO = new ScoreRecordVO();
            BeanUtils.copyProperties(scoreRecord, scoreRecordVO);
            if (null != scoreRecordVO.getCreateTime()) {
                scoreRecordVO.setStrCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, scoreRecordVO.getCreateTime()));
            }
            scoreRecordVOList.add(scoreRecordVO);
        }
        return scoreRecordVOList;
    }

    @Override
    public List<ScoreConsumeRecord> getScoreConsumeRecordList(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            ScoreConsumeRecord record = new ScoreConsumeRecord();
            record.setCustomerId(customerId);
            List<ScoreConsumeRecord> scoreConsumeRecordList = scoreConsumeRecordService.selectScoreConsumeRecordList(record);
            if (CollectionUtils.isEmpty(scoreConsumeRecordList)) {
                logger.info("ts{}用户{}无积分消耗记录", ts, customerId);
                return new ArrayList<>();
            }
            return scoreConsumeRecordList;
        } catch (Exception e) {
            logger.error("ts{}查询积分消耗记录异常", ts, e);
            return null;
        }
    }

    @Override
    public List<ScoreRecordVO> getScoreConsumeRecord(List<ScoreConsumeRecord> scoreConsumeRecordList) {
        long ts = DateUtils.getTimeMillis();
        try {
            if (CollectionUtils.isEmpty(scoreConsumeRecordList)) {
                return new ArrayList<>();
            }
            logger.info("ts{} 积分消耗记录条数{}", ts, scoreConsumeRecordList.size());
            List<ScoreRecordVO> scoreRecordVOList = scoreRecord2ScoreRecordVOList(scoreConsumeRecordList);
            return scoreRecordVOList;
        } catch (Exception e) {
            logger.error("ts{}查询积分消耗记录异常", ts, e);
            return null;
        }
    }

    @Override
    public List<ScoreRecordVO> getScoreConsumeRecord(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            ScoreConsumeRecord record = new ScoreConsumeRecord();
            record.setCustomerId(customerId);
            List<ScoreConsumeRecord> scoreConsumeRecordList = scoreConsumeRecordService.selectScoreConsumeRecordList(record);
            if (CollectionUtils.isEmpty(scoreConsumeRecordList)) {
                logger.info("ts{}用户{}无积分消耗记录", ts, customerId);
                return new ArrayList<>();
            }
            logger.info("ts{}用户{}积分消耗记录条数{}", ts, customerId, scoreConsumeRecordList.size());
            List<ScoreRecordVO> scoreRecordVOList = scoreRecord2ScoreRecordVOList(scoreConsumeRecordList);
            return scoreRecordVOList;
        } catch (Exception e) {
            logger.error("ts{}查询积分消耗记录异常", ts, e);
            return null;
        }
    }

    @Override
    public Integer isGetNewUserGift(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Long customerId = getCustomerId(ts, request);
            logger.info("ts{}查询用户{}是否领取新用户见面礼开始", ts, customerId);
            ScoreRecord scoreRecord = new ScoreRecord();
            scoreRecord.setCustomerId(customerId);
            scoreRecord.setScoreType(ScoreTypeEnum.NEW_USER_GIFT.getCode());
            scoreRecord.setYn(YNEnum.NO.getCode());
            List<ScoreRecord> scoreRecordList = scoreRecordService.selectScoreRecordList(scoreRecord);
            if (CollectionUtils.isEmpty(scoreRecordList)) {
                return YNEnum.NO.getCode();
            }
            return YNEnum.YES.getCode();
        } catch (Exception e) {
            logger.error("ts{}是否领取新用户见面礼异常", ts, e);
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addNewUserGift(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            Customer customer = CommonUtils.getCustomerByRequest(request);
            Long customerId = customer.getCustomerId();
            logger.info("ts{}用户{}领取新用户见面礼开始", ts, customerId);
            ScoreRecord scoreRecord = new ScoreRecord();
            scoreRecord.setCustomerId(customerId);
            scoreRecord.setScoreType(ScoreTypeEnum.NEW_USER_GIFT.getCode());
            scoreRecord.setYn(YNEnum.NO.getCode());
            List<ScoreRecord> scoreRecordList = scoreRecordService.selectScoreRecordList(scoreRecord);
            if (CollectionUtils.isEmpty(scoreRecordList)) {
                //scoreRecord = constructScoreRecord(customer, ScoreTypeEnum.NEW_USER_GIFT);
                //int insertResult = scoreRecordService.insertScoreRecord(scoreRecord);
                //logger.info("ts{}用户{}领取新用户见面礼结果{}", ts, scoreRecord.getCustomerId(), insertResult);
                //Long score = customer.getScore();
                //score = null == score ? Long.valueOf(NumberConstants.ZERO) : score;
                //score = score + scoreRecord.getScoreNumber();
                //customer.setScore(score);
                //int updateResult = customerService.updateCustomer(customer);
                //logger.info("ts{}用户{}更新积分结果{}", ts, scoreRecord.getCustomerId(), updateResult);
                Map<String, Integer> map = updateScore(ts, customer, ScoreTypeEnum.NEW_USER_GIFT, null);
                int insertResult = map.get(INSERT_RESULT);
                int updateResult = map.get(INSERT_RESULT);

                if (insertResult > 0 && updateResult > 0) {
                    logger.info("ts{}用户{}领取新用户见面礼成功", ts, customerId);
                    return YNEnum.YES.getCode();
                }
                logger.info("ts{}用户{}领取新用户见面礼失败", ts, customerId);
                return YNEnum.NO.getCode();
            }
            logger.info("ts{}用户{}已领取新用户见面礼", ts, customerId);
            return YNEnum.NO.getCode();
        } catch (Exception e) {
            logger.error("ts{}领取新用户见面礼异常", ts, e);
            return null;
        }
    }

    private Long getCustomerId(Long ts, HttpServletRequest request) {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        if (null == customer || null == customer.getCustomerId()) {
            logger.info("ts:{}，未找到用户信息", ts);
            return null;
        }
        Long customerId = customer.getCustomerId();
        return customerId;
    }
}
